// Header Protection
#ifndef _NOTIFICATION_H_
#define _NOTIFICATION_H_

// Include Files
#include "Definitions.h"

// Namespace
namespace IE
{
	/////////////////////////////////////////////////////////////////////////////////
	// When an event is raised, a notification is created and added to the queue of 
	//     each registered event listener. 
	class ABCNotification
	{
	public:     // methods
		inline ABCNotification() { }
		inline virtual ~ABCNotification() = 0 { }

		// Call process in the derived class, which has a specific type of listener 
		//     and event argument.
		// _pListener : IListener * - the event listener to process the event in
		virtual inline void Process( IListener *_pListener ) = 0;

	private:    // dummy definitions
		ABCNotification( ABCNotification const & );
		ABCNotification &operator =( ABCNotification const & );
	};

	/////////////////////////////////////////////////////////////////////////////////
	// A notification for a specific type of listener and event argument.
	// listener_t : template - the type of the listener for this notification
	// eventarg_t : template - the type of event argument for this notification
	template< class listener_t, class eventarg_t >
	class CNotification : public ABCNotification
	{
	public:     // methods

		// _pArg : eventarg_t * - the event argument from the raised event
		// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler for 
		//     the raised event
		inline CNotification( 
			eventarg_t *_pArg, void (listener_t::*_pHandler)(eventarg_t &) ) : 
		m_pArg(_pArg), m_pHandler(_pHandler)
		{ m_pArg->AddRef(); }
		inline ~CNotification() { m_pArg->Release(); }

		// Call the event handler from the listener with the event argument.
		// _pListener : IListener * - the event listener to process the event in
		inline void Process( IListener *_pListener )
		{
			( ((listener_t*)_pListener)->*m_pHandler )(*m_pArg);
		}

	private:    // data
		eventarg_t *m_pArg;
		void (listener_t::*m_pHandler)(eventarg_t &);

	private:    // dummy definitions
		CNotification( CNotification const & );
		CNotification &operator =( CNotification const & );
	};
}

// Header Protection
#endif // _NOTIFICATION_H_
